import numpy as np
import os
import sys
from sklearn.decomposition import PCA


class pca(object):

    def __init__(self, **kwargs):
        self.wd = kwargs.get('wd', os.getcwd())

        os.makedirs(os.path.join(self.wd, 'pca'), exist_ok=True)
        self.pcaDir = os.path.join(self.wd, 'pca')

    def loadData(self, **kwargs):
        fileName = kwargs.get('fileName', None)
        fileNameList = kwargs.get('fileNameList', None)
        fmt = kwargs.get('fmt', 'csv')
        delimiter = kwargs.get('delimiter', None)

        _data = np.array(())

        if fileName:
            _data = np.loadtxt(os.path.join(self.wd, '{}.{}'.format(fileName, fmt)), delimiter=delimiter).flatten()
        elif fileNameList:
            _n = len(fileNameList)
            for _f in fileNameList:
                _d = np.loadtxt(os.path.join(self.wd, '{}.{}'.format(_f, fmt)), delimiter=delimiter).flatten()
                _data = np.append(_data, _d)
            _data = _data.reshape((_n, -1))
        else:
            print('请输入文件名或文件名列表')
            sys.exit(0)

        return _data

    def compute(self, **kwargs):
        numComponents = kwargs.get('numComponents', 30)
        _x = kwargs.get('x', np.random.random((10, 10)))
        fileName = kwargs.get('fileName', '')

        n_samples, n_features = _x.shape
        _mean = np.mean(_x, axis=1)
        X = _x - np.tile(_mean, (_x.shape[1], 1)).T
        U, S, VT = np.linalg.svd(X, full_matrices=0)

        explained_variance_ = (S ** 2) / (n_samples - 1)
        total_var = explained_variance_.sum()
        explained_variance_ratio_ = explained_variance_ / total_var
        _ratio = np.hstack(
            (explained_variance_ratio_.reshape((-1, 1)), np.cumsum(explained_variance_ratio_).reshape(-1, 1)))

        # SAVING STATISTICS
        np.savetxt(os.path.join(self.pcaDir, '{}-pca-{}-u.csv'.format(fileName, numComponents)), U[:, :numComponents], fmt='%1.5f',
                   delimiter='\t')
        np.savetxt(os.path.join(self.pcaDir, '{}-pca-{}-s.csv'.format(fileName, numComponents)), S[:numComponents], fmt='%1.5f',
                   delimiter='\t')
        np.savetxt(os.path.join(self.pcaDir, '{}-pca-{}-vt.csv'.format(fileName, numComponents)), VT[:numComponents],
                   fmt='%1.5f', delimiter='\t')
        np.savetxt(os.path.join(self.pcaDir, '{}-pca-mean.csv'.format(fileName)), _mean, fmt='%1.5f', delimiter='\t')
        np.savetxt(os.path.join(self.pcaDir, '{}-pca-{}-varratio.csv'.format(fileName, numComponents)), _ratio, fmt='%1.5f',
                   delimiter='\t')
        np.savetxt(os.path.join(self.pcaDir, '{}-pca-{}-var.csv'.format(fileName, numComponents)), explained_variance_, fmt='%1.5f',
                   delimiter='\t')
